/**
 *1、 find、findIndex
 * find:参数是一个回调函数，所有数组成员依次执行该回调函数，直到找出第一个返回值为true的成员，然后返回该成员。如果没有符合条件的成员，则返回undefined
 * findIndex: 返回第一个符合条件的数组成员的位置，如果所有成员都不符合条件，则返回-1
 */
// [].find(function(value, index, arr) { return value > 0 }) 当前的值、当前的位置、原数组
const a = [1, 2, 3]
a.find((item, index, arr) => item > 1)  // 2

// findIndex
a.findIndex((item, index, arr) => item > 1) // 1

// 两个方法都可以接受第二个参数，用来绑定回调函数的this对象
function filter(value) {
  return value > this.age
}
const a1 = { age: 2 }
a.find(filter, a1) // 3
a.findIndex(filter, a1) // 2

// 两个方法都可以借助Object.is发现NaN，弥补了数组的indexOf方法的不足
/**
1、Object.is(value1,value2) 返回布尔值 表示两个参数是否同一个值
都是 undefined、都是 null
都是 true 或都是 false
都是相同长度、相同字符、按相同顺序排列的字符串
都是相同对象（意味着都是同一个对象的值引用）
都是数字且
都是 + 0
都是 - 0
都是 NaN
都是同一个值，非零且都不是 NaN

2、
Object.is() 与 == 不同。== 运算符在判断相等前对两边的变量（如果它们不是同一类型）进行强制转换（这种行为将 "" == false 判断为 true），而 Object.is 不会强制转换两边的值。
Object.is() 与 === 也不相同。差别是它们对待有符号的零和 NaN 不同，例如，=== 运算符（也包括 == 运算符）将数字 -0 和 +0 视为相等，而将 Number.NaN 与 NaN 视为不相等。
 * */

const a3 = [NaN]
a3.indexOf(NaN) // -1
a3.find(item => Object.is(NaN, item)) // NaN
a3.findIndex(item => Object.is(NaN, item)) // 0


/**
 * 2、fill 给定值，填充一个数组。 填充的类型为对象，那么被赋值的是同一个内存地址的对象，而不是深拷贝对象。
 * array.fill(value,start,end) 填充值、起始位置、结束位置
 */
const a4 = [1, 2, 3]
a4.fill('a4', 1, 2) // [1,'a4',3]
// 填充的类型为对象，那么被赋值的是同一个内存地址的对象，而不是深拷贝对象。
const a5 = new Array(3).fill({ name: 'a5' }) // [{ name: 'a5' },{ name: 'a5' },{ name: 'a5' }]
a5[0].name = 'a55' // // [{ name: 'a55' },{ name: 'a55' },{ name: 'a55' }]


/**
 * 3、keys()是对键名的遍历、values()是对键值的遍历，entries()是对键值对的遍历。
 * 数组原型实现了Iterator接口，可以for...of循环
 */
for (let index of a.keys()) {
  console.log(index) // 0 1 2
}
for (let index of a.values()) {
  console.log(index) // 1 2 3
}
for (let [index, item] of a.entries()) {
  console.log(index, item)
  // 0 1
  // 1 2
  // 2 3
}

// 如果不使用for...of循环，可以手动调用遍历器对象的next方法，进行遍历。
const entries = a.entries()
console.log(entries.next().value); //entries.next(): { value: [ 0, 1 ], done: false }
console.log(entries.next().value); //entries.next(): { value: [ 1, 2 ], done: false }
console.log(entries.next().value); //entries.next(): { value: [ 2, 3 ], done: false }
console.log(entries.next().value); //entries.next(): { value: undefined, done: true }

/**
 * 4、includes 某个数组是否包含给定的值
 * 第二个参数表示搜索的起始位置，默认为0。 如果是负数 倒数的位置 大于数组长度则从0开始
 * Map 结构的has方法，是用来查找键名的，比如Map.prototype.has(key)、WeakMap.prototype.has(key)、Reflect.has(target, propertyKey)。
  Set 结构的has方法，是用来查找值的，比如Set.prototype.has(value)、WeakSet.prototype.has(value)
 */
// includes可以识别NaN typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)
[NaN].includes(NaN)  // true


/**
 * 5、at 数组实例、字符串、类数组接受一个整数作为参数，返回对应位置的成员，支持负索引。
 */
a[a.length - 1] // 3
a.at(-1)  // 3


/**
 * 6、flat、flatMap
 * flat()方法的参数写成一个整数，表示想要拉平的层数，默认为1   保证一维数组 Infinity作参数
 * flatMap()方法对原数组的每个成员执行一个函数（相当于执行Array.prototype.map()），然后对返回值组成的数组执行flat()方法。该方法返回一个新数组，不改变原数组。
 * 第一个参数是一个遍历函数，当前数组成员、当前数组成员的位置（从零开始）、原数组       第二个参数，用来绑定遍历函数里面的this。
 */

// 跳过空位
[1, 2, , 4, 5].flat()  // [1, 2, 4, 5]

[2, 3, 4].flatMap((x) => [x, x * 2]) // 相当于 [[2, 4], [3, 6], [4, 8]].flat()       [2, 4, 3, 6, 4, 8]
